Specify the tissue of interest, run the boilerplate code which sets up the functions and environment, load the tissue object.

tissue_of_interest = "Marrow"
library(here)
source(here("00_data_ingest", "02_tissue_analysis_rmd", "boilerplate.R"))
tiss = load_tissue_facs(tissue_of_interest)

Visualize top genes in principal components

Later on (in FindClusters and TSNE) you will pick a number of principal components to use. This has the effect of keeping the major directions of variation in the data and, ideally, supressing noise. There is no correct answer to the number to use, but a decent rule of thumb is to go until the plot plateaus.

PCElbowPlot(object = tiss)

Choose the number of principal components to use.

# Set number of principal components. 
n.pcs = 15

The clustering is performed based on a nearest neighbors graph. Cells that have similar expression will be joined together. The Louvain algorithm looks for groups of cells with high modularity–more connections within the group than between groups. The resolution parameter determines the scale…higher resolution will give more clusters, lower resolution will give fewer.

For the top-level clustering, aim to under-cluster instead of over-cluster. It will be easy to subset groups and further analyze them below.

# Set resolution 
res.used <- 0.5
tiss <- FindClusters(object = tiss, reduction.type = "pca", dims.use = 1:n.pcs, 
    resolution = res.used, print.output = 0, save.SNN = TRUE)

To visualize

# If cells are too spread out, you can raise the perplexity. If you have few cells, try a lower perplexity (but never less than 10).
tiss <- RunTSNE(object = tiss, dims.use = 1:n.pcs, seed.use = 10, perplexity=84)
# note that you can set do.label=T to help label individual clusters
TSNEPlot(object = tiss, do.label = T)

Check expression of genes of interset.

Dotplots let you see the intensity of exppression and the fraction of cells expressing for each of your genes of interest.

How big are the clusters?

table(tiss@ident)

  0   1   2   3   4   5   6   7   8   9  10  11  12  13  14 
743 681 522 453 392 373 348 337 302 217 196 173 172 104  24 

Which markers identify a specific cluster?

clust.markers <- FindMarkers(object = tiss, ident.1 = 0, only.pos = TRUE, min.pct = 0.25, thresh.use = 0.25)

   |                                                  | 0 % ~calculating  
   |+                                                 | 1 % ~06m 06s      
   |+                                                 | 2 % ~06m 43s      
   |++                                                | 3 % ~06m 26s      
   |++                                                | 4 % ~06m 14s      
   |+++                                               | 5 % ~06m 10s      
   |+++                                               | 6 % ~06m 05s      
   |++++                                              | 7 % ~05m 60s      
   |++++                                              | 8 % ~05m 57s      
   |+++++                                             | 9 % ~05m 53s      
   |+++++                                             | 10% ~05m 51s      
   |++++++                                            | 11% ~05m 48s      
   |++++++                                            | 12% ~05m 45s      
   |+++++++                                           | 13% ~05m 41s      
   |+++++++                                           | 14% ~05m 39s      
   |++++++++                                          | 15% ~05m 35s      
   |++++++++                                          | 16% ~05m 31s      
   |+++++++++                                         | 17% ~05m 27s      
   |+++++++++                                         | 18% ~05m 24s      
   |++++++++++                                        | 19% ~05m 20s      
   |++++++++++                                        | 20% ~05m 15s      
   |+++++++++++                                       | 21% ~05m 11s      
   |+++++++++++                                       | 22% ~05m 08s      
   |++++++++++++                                      | 23% ~05m 06s      
   |++++++++++++                                      | 24% ~05m 02s      
   |+++++++++++++                                     | 25% ~04m 57s      
   |+++++++++++++                                     | 26% ~04m 53s      
   |++++++++++++++                                    | 27% ~04m 49s      
   |++++++++++++++                                    | 28% ~04m 45s      
   |+++++++++++++++                                   | 29% ~04m 41s      
   |+++++++++++++++                                   | 30% ~04m 38s      
   |++++++++++++++++                                  | 31% ~04m 34s      
   |++++++++++++++++                                  | 32% ~04m 30s      
   |+++++++++++++++++                                 | 33% ~04m 26s      
   |+++++++++++++++++                                | 34% ~04m 22s      
   |++++++++++++++++++                                | 35% ~04m 18s      
   |++++++++++++++++++                                | 36% ~04m 14s      
   |+++++++++++++++++++                               | 37% ~04m 11s      
   |+++++++++++++++++++                               | 38% ~04m 10s      
   |++++++++++++++++++++                              | 39% ~04m 06s      
   |++++++++++++++++++++                              | 40% ~04m 02s      
   |+++++++++++++++++++++                             | 41% ~03m 57s      
   |+++++++++++++++++++++                             | 42% ~03m 53s      
   |++++++++++++++++++++++                            | 43% ~03m 49s      
   |++++++++++++++++++++++                            | 44% ~03m 44s      
   |+++++++++++++++++++++++                           | 45% ~03m 40s      
   |+++++++++++++++++++++++                           | 46% ~03m 36s      
   |++++++++++++++++++++++++                          | 47% ~03m 32s      
   |++++++++++++++++++++++++                          | 48% ~03m 27s      
   |+++++++++++++++++++++++++                         | 49% ~03m 23s      
   |+++++++++++++++++++++++++                         | 50% ~03m 19s      
   |++++++++++++++++++++++++++                        | 51% ~03m 15s      
   |++++++++++++++++++++++++++                        | 52% ~03m 11s      
   |+++++++++++++++++++++++++++                       | 53% ~03m 07s      
   |+++++++++++++++++++++++++++                       | 54% ~03m 03s      
   |++++++++++++++++++++++++++++                      | 55% ~02m 59s      
   |++++++++++++++++++++++++++++                     | 56% ~02m 55s      
   |+++++++++++++++++++++++++++++                     | 57% ~02m 51s      
   |+++++++++++++++++++++++++++++                     | 58% ~02m 47s      
   |++++++++++++++++++++++++++++++                    | 59% ~02m 43s      
   |++++++++++++++++++++++++++++++                    | 60% ~02m 39s      
   |+++++++++++++++++++++++++++++++                   | 61% ~02m 35s      
   |+++++++++++++++++++++++++++++++                   | 62% ~02m 31s      
   |++++++++++++++++++++++++++++++++                  | 63% ~02m 27s      
   |++++++++++++++++++++++++++++++++                  | 64% ~02m 23s      
   |+++++++++++++++++++++++++++++++++                 | 65% ~02m 19s      
   |+++++++++++++++++++++++++++++++++                 | 66% ~02m 15s      
   |++++++++++++++++++++++++++++++++++                | 67% ~02m 11s      
   |++++++++++++++++++++++++++++++++++               | 68% ~02m 07s      
   |+++++++++++++++++++++++++++++++++++               | 69% ~02m 03s      
   |+++++++++++++++++++++++++++++++++++               | 70% ~01m 59s      
   |++++++++++++++++++++++++++++++++++++              | 71% ~01m 55s      
   |++++++++++++++++++++++++++++++++++++              | 72% ~01m 51s      
   |+++++++++++++++++++++++++++++++++++++             | 73% ~01m 47s      
   |+++++++++++++++++++++++++++++++++++++             | 74% ~01m 44s      
   |++++++++++++++++++++++++++++++++++++++            | 75% ~01m 40s      
   |++++++++++++++++++++++++++++++++++++++            | 76% ~01m 35s      
   |+++++++++++++++++++++++++++++++++++++++           | 77% ~01m 31s      
   |+++++++++++++++++++++++++++++++++++++++          | 78% ~01m 28s      
   |++++++++++++++++++++++++++++++++++++++++          | 79% ~01m 24s      
   |++++++++++++++++++++++++++++++++++++++++         | 80% ~01m 20s      
   |+++++++++++++++++++++++++++++++++++++++++         | 81% ~01m 15s      
   |+++++++++++++++++++++++++++++++++++++++++         | 82% ~01m 11s      
   |++++++++++++++++++++++++++++++++++++++++++        | 83% ~01m 08s      
   |++++++++++++++++++++++++++++++++++++++++++        | 84% ~01m 04s      
   |+++++++++++++++++++++++++++++++++++++++++++       | 85% ~60s          
   |+++++++++++++++++++++++++++++++++++++++++++       | 86% ~56s          
   |++++++++++++++++++++++++++++++++++++++++++++      | 87% ~52s          
   |++++++++++++++++++++++++++++++++++++++++++++      | 88% ~48s          
   |+++++++++++++++++++++++++++++++++++++++++++++     | 89% ~44s          
   |+++++++++++++++++++++++++++++++++++++++++++++    | 90% ~40s          
   |++++++++++++++++++++++++++++++++++++++++++++++    | 91% ~36s          
   |++++++++++++++++++++++++++++++++++++++++++++++   | 92% ~32s          
   |+++++++++++++++++++++++++++++++++++++++++++++++   | 93% ~28s          
   |+++++++++++++++++++++++++++++++++++++++++++++++   | 94% ~24s          
   |++++++++++++++++++++++++++++++++++++++++++++++++  | 95% ~20s          
   |++++++++++++++++++++++++++++++++++++++++++++++++  | 96% ~16s          
   |+++++++++++++++++++++++++++++++++++++++++++++++++ | 97% ~12s          
   |+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~08s          
   |++++++++++++++++++++++++++++++++++++++++++++++++++| 99% ~04s          
   |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed = 06m 40s
print(x = head(x= clust.markers, n = 10))

Compare to figshare annotations

rr figshare_annotation = filter(figshare_annotation, tissue == tissue_of_interest) tiss@meta.data[, ‘figshare_annotation’] <- NA tiss@meta.data[as.character(figshare_annotation$cell), ‘figshare_annotation’] <- as.character(figshare_annotation$cell_ontology_class) TSNEPlot(object = tiss, do.return = TRUE, group.by = _annotation)

Error in seq.default(h[1], h[2], length.out = n) : 
  'to' must be a finite number

Assigning cell type identity to clusters

At a coarse level, we can use canonical markers to match the unbiased clustering to known cell types:

0: alpha 1: beta 2: beta 3: exocrine 4: duct 5: delta 6: gamma 7: endothelial 8: immune 9: stellate

Checking for batch effects

Color by metadata, like plate barcode, to check for batch effects.

Print a table showing the count of cells in each identity category from each plate.

Subset and iterate

We can repeat the above analysis on a subset of cells, defined using cluster IDs or some other metadata. This is a good way to drill down and find substructure.

Subset == T and NK cells (Cluster 7)

Run Principal Component Analysis.

Later on (in FindClusters and TSNE) you will pick a number of principal components to use. This has the effect of keeping the major directions of variation in the data and, ideally, supressing noise. There is no correct answer to the number to use, but a decent rule of thumb is to go until the plot plateaus.

Choose the number of principal components to use.

The clustering is performed based on a nearest neighbors graph. Cells that have similar expression will be joined together. The Louvain algorithm looks for groups of cells with high modularity–more connections within the group than between groups. The resolution parameter determines the scale…higher resolution will give more clusters, lower resolution will give fewer.

To visualize

Check expression of genes of interset.

Dotplots let you see the intensity of exppression and the fraction of cells expressing for each of your genes of interest.

How big are the clusters?

Checking for batch effects

Color by metadata, like plate barcode, to check for batch effects.

Print a table showing the count of cells in each identity category from each plate.

Assigning subcell_ontology_classs

For the subsets, we produce subcell_ontology_classs. These will be written back as metadata in the original object, so we can see all subcell_ontology_classs together.

If some of the clusters you find in the subset deserve additional cell_ontology_class, you can add that right here. Use NA for clusters for which no subcell_ontology_class is needed.

When you save the subtissue, please give it a name.

Export the final metadata

So that Biohub can easily combine all your cell_ontology_classs, please export them as a simple csv.

Write the cell ontology and free annotations to CSV.

LS0tCnRpdGxlOiAiTWFycm93IEZBQ1MgTm90ZWJvb2siCm91dHB1dDoKICBodG1sX2RvY3VtZW50OiBkZWZhdWx0CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAotLS0KClNwZWNpZnkgdGhlIHRpc3N1ZSBvZiBpbnRlcmVzdCwgcnVuIHRoZSBib2lsZXJwbGF0ZSBjb2RlIHdoaWNoIHNldHMgdXAgdGhlIGZ1bmN0aW9ucyBhbmQgZW52aXJvbm1lbnQsIGxvYWQgdGhlIHRpc3N1ZSBvYmplY3QuCgpgYGB7cn0KdGlzc3VlX29mX2ludGVyZXN0ID0gIk1hcnJvdyIKbGlicmFyeShoZXJlKQpzb3VyY2UoaGVyZSgiMDBfZGF0YV9pbmdlc3QiLCAiMDJfdGlzc3VlX2FuYWx5c2lzX3JtZCIsICJib2lsZXJwbGF0ZS5SIikpCnRpc3MgPSBsb2FkX3Rpc3N1ZV9mYWNzKHRpc3N1ZV9vZl9pbnRlcmVzdCkKYGBgCgpWaXN1YWxpemUgdG9wIGdlbmVzIGluIHByaW5jaXBhbCBjb21wb25lbnRzCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9OH0KUENIZWF0bWFwKG9iamVjdCA9IHRpc3MsIHBjLnVzZSA9IDE6MywgY2VsbHMudXNlID0gNTAwLCBkby5iYWxhbmNlZCA9IFRSVUUsIGxhYmVsLmNvbHVtbnMgPSBGQUxTRSwgbnVtLmdlbmVzID0gOCkKYGBgCgpMYXRlciBvbiAoaW4gRmluZENsdXN0ZXJzIGFuZCBUU05FKSB5b3Ugd2lsbCBwaWNrIGEgbnVtYmVyIG9mIHByaW5jaXBhbCBjb21wb25lbnRzIHRvIHVzZS4gVGhpcyBoYXMgdGhlIGVmZmVjdCBvZiBrZWVwaW5nIHRoZSBtYWpvciBkaXJlY3Rpb25zIG9mIHZhcmlhdGlvbiBpbiB0aGUgZGF0YSBhbmQsIGlkZWFsbHksIHN1cHJlc3Npbmcgbm9pc2UuIFRoZXJlIGlzIG5vIGNvcnJlY3QgYW5zd2VyIHRvIHRoZSBudW1iZXIgdG8gdXNlLCBidXQgYSBkZWNlbnQgcnVsZSBvZiB0aHVtYiBpcyB0byBnbyB1bnRpbCB0aGUgcGxvdCBwbGF0ZWF1cy4KCmBgYHtyfQpQQ0VsYm93UGxvdChvYmplY3QgPSB0aXNzKQpgYGAKCkNob29zZSB0aGUgbnVtYmVyIG9mIHByaW5jaXBhbCBjb21wb25lbnRzIHRvIHVzZS4KYGBge3J9CiMgU2V0IG51bWJlciBvZiBwcmluY2lwYWwgY29tcG9uZW50cy4gCm4ucGNzID0gMTUKYGBgCgoKVGhlIGNsdXN0ZXJpbmcgaXMgcGVyZm9ybWVkIGJhc2VkIG9uIGEgbmVhcmVzdCBuZWlnaGJvcnMgZ3JhcGguIENlbGxzIHRoYXQgaGF2ZSBzaW1pbGFyIGV4cHJlc3Npb24gd2lsbCBiZSBqb2luZWQgdG9nZXRoZXIuIFRoZSBMb3V2YWluIGFsZ29yaXRobSBsb29rcyBmb3IgZ3JvdXBzIG9mIGNlbGxzIHdpdGggaGlnaCBtb2R1bGFyaXR5LS1tb3JlIGNvbm5lY3Rpb25zIHdpdGhpbiB0aGUgZ3JvdXAgdGhhbiBiZXR3ZWVuIGdyb3Vwcy4gVGhlIHJlc29sdXRpb24gcGFyYW1ldGVyIGRldGVybWluZXMgdGhlIHNjYWxlLi4uaGlnaGVyIHJlc29sdXRpb24gd2lsbCBnaXZlIG1vcmUgY2x1c3RlcnMsIGxvd2VyIHJlc29sdXRpb24gd2lsbCBnaXZlIGZld2VyLgoKRm9yIHRoZSB0b3AtbGV2ZWwgY2x1c3RlcmluZywgYWltIHRvIHVuZGVyLWNsdXN0ZXIgaW5zdGVhZCBvZiBvdmVyLWNsdXN0ZXIuIEl0IHdpbGwgYmUgZWFzeSB0byBzdWJzZXQgZ3JvdXBzIGFuZCBmdXJ0aGVyIGFuYWx5emUgdGhlbSBiZWxvdy4KCmBgYHtyfQojIFNldCByZXNvbHV0aW9uIApyZXMudXNlZCA8LSAwLjUKCnRpc3MgPC0gRmluZENsdXN0ZXJzKG9iamVjdCA9IHRpc3MsIHJlZHVjdGlvbi50eXBlID0gInBjYSIsIGRpbXMudXNlID0gMTpuLnBjcywgCiAgICByZXNvbHV0aW9uID0gcmVzLnVzZWQsIHByaW50Lm91dHB1dCA9IDAsIHNhdmUuU05OID0gVFJVRSkKYGBgCgpUbyB2aXN1YWxpemUgCmBgYHtyfQojIElmIGNlbGxzIGFyZSB0b28gc3ByZWFkIG91dCwgeW91IGNhbiByYWlzZSB0aGUgcGVycGxleGl0eS4gSWYgeW91IGhhdmUgZmV3IGNlbGxzLCB0cnkgYSBsb3dlciBwZXJwbGV4aXR5IChidXQgbmV2ZXIgbGVzcyB0aGFuIDEwKS4KdGlzcyA8LSBSdW5UU05FKG9iamVjdCA9IHRpc3MsIGRpbXMudXNlID0gMTpuLnBjcywgc2VlZC51c2UgPSAxMCwgcGVycGxleGl0eT04NCkKYGBgCgpgYGB7cn0KIyBub3RlIHRoYXQgeW91IGNhbiBzZXQgZG8ubGFiZWw9VCB0byBoZWxwIGxhYmVsIGluZGl2aWR1YWwgY2x1c3RlcnMKVFNORVBsb3Qob2JqZWN0ID0gdGlzcywgZG8ubGFiZWwgPSBUKQpgYGAKCkNoZWNrIGV4cHJlc3Npb24gb2YgZ2VuZXMgb2YgaW50ZXJzZXQuCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD04NCwgZmlnLndpZHRoPTE1fQpnZW5lc190b19jaGVjayA9IGMoJ0l0Z2FtJywgJ0lsN3InLCAnS2l0JywgJ0F0eG4xJywgJ0ZjZ3IzJywgJ0ZsdDMnLCAnQ2QzNCcsICdTbGFtZjEnLCAnR3ByNTYnLCAnU3RtbjEnLCAnVG1lbTE3NmInLCAgJ0l0Z2FsJywgJ0l0Z2F4JywgJ0VtcjEnLCAnQ2Q2OCcsICdGY2dyNCcsICdNcGVnMScsICdJdGdiMicsICdBaG5haycsICdQbGQ0JywgJ0NkM2UnLCAnQ2Q0JywgJ0NkOGEnLCAnTHk2ZCcsICdDZDI3JywgJ0NyMicsICdGY2VyMmEnLCAnQ2QyJywgJ0NkNycsICdNbWUnLCAnVGh5MScsICdDZDE5JywgJ01zNGExJywgJ0NkNzQnLCAnQ2hjaGQxMCcsICdDbnAnLCAnQ2Q3OWEnLCAnQ2Q3OWInLCAnVnByZWIzJywgJ0tscmIxYScsICdTMTAwYTExJywgJ0x0ZicsICdOZ3AnLCAnRmNlcjFnJywgJ1BnbHlycDEnLCAnTGNuMicsICdDYW1wJywgJ0hwJywgJ0x5Nmc2YycsICdMeTZnNmUnLCAnUHRwcmMnKQojZ2VuZXNfdG9fY2hlY2sgPSBjKCdBbGInLCAnQ3lwMmYyJywgJ0N5cDJlMScsICdIYW1wJykKCkZlYXR1cmVQbG90KHRpc3MsIGdlbmVzX3RvX2NoZWNrLCBwdC5zaXplID0gMSwgbkNvbCA9IDMpCmBgYAoKRG90cGxvdHMgbGV0IHlvdSBzZWUgdGhlIGludGVuc2l0eSBvZiBleHBwcmVzc2lvbiBhbmQgdGhlIGZyYWN0aW9uIG9mIGNlbGxzIGV4cHJlc3NpbmcgZm9yIGVhY2ggb2YgeW91ciBnZW5lcyBvZiBpbnRlcmVzdC4KCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD0zOX0KIyBUbyBjaGFuZ2UgdGhlIHktYXhpcyB0byBzaG93IHJhdyBjb3VudHMsIGFkZCB1c2UucmF3ID0gVC4KRG90UGxvdCh0aXNzLCBnZW5lc190b19jaGVjaywgcGxvdC5sZWdlbmQgPSBUKQpgYGAKCkhvdyBiaWcgYXJlIHRoZSBjbHVzdGVycz8KYGBge3J9CnRhYmxlKHRpc3NAaWRlbnQpCmBgYAoKV2hpY2ggbWFya2VycyBpZGVudGlmeSBhIHNwZWNpZmljIGNsdXN0ZXI/CgpgYGB7cn0KY2x1c3QubWFya2VycyA8LSBGaW5kTWFya2VycyhvYmplY3QgPSB0aXNzLCBpZGVudC4xID0gMCwgb25seS5wb3MgPSBUUlVFLCBtaW4ucGN0ID0gMC4yNSwgdGhyZXNoLnVzZSA9IDAuMjUpCmBgYAoKYGBge3J9CnByaW50KHggPSBoZWFkKHg9IGNsdXN0Lm1hcmtlcnMsIG4gPSAxMCkpCmBgYAoKPCEtLSBZb3UgY2FuIGFsc28gY29tcHV0ZSBhbGwgbWFya2VycyBmb3IgYWxsIGNsdXN0ZXJzIGF0IG9uY2UuIFRoaXMgbWF5IHRha2Ugc29tZSB0aW1lLiAtLT4KPCEtLSBgYGB7cn0gLS0+CjwhLS0gdGlzcy5tYXJrZXJzIDwtIEZpbmRBbGxNYXJrZXJzKG9iamVjdCA9IHRpc3MsIG9ubHkucG9zID0gVFJVRSwgbWluLnBjdCA9IDAuMjUsIHRocmVzaC51c2UgPSAwLjI1KSAtLT4KPCEtLSBgYGAgLS0+CjwhLS0gYGBge3J9IC0tPgo8IS0tIGhlYWQodGlzcy5tYXJrZXJzKSAtLT4KPCEtLSBgYGAgLS0+Cgo8IS0tIERpc3BsYXkgdGhlIHRvcCBtYXJrZXJzIHlvdSBjb21wdXRlZCBhYm92ZS4gLS0+CjwhLS0gYGBge3J9IC0tPgo8IS0tIHRpc3MubWFya2VycyAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIHRvcF9uKDUsIGF2Z19sb2dGQykgLS0+CjwhLS0gYGBgIC0tPgoKQ29tcGFyZSB0byBmaWdzaGFyZSBhbm5vdGF0aW9ucwpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmZpZ3NoYXJlX2Fubm90YXRpb24gPSByZWFkX2NzdihoZXJlKCIwMF9kYXRhX2luZ2VzdCIsIjAwX2ZhY3NfcmF3X2RhdGEiLCAiYW5ub3RhdGlvbnNfRkFDUy5jc3YiKSkKZmlnc2hhcmVfYW5ub3RhdGlvbiA9IGZpbHRlcihmaWdzaGFyZV9hbm5vdGF0aW9uLCB0aXNzdWUgPT0gdGlzc3VlX29mX2ludGVyZXN0KQp0aXNzQG1ldGEuZGF0YVssICdmaWdzaGFyZV9hbm5vdGF0aW9uJ10gPC0gTkEKdGlzc0BtZXRhLmRhdGFbYXMuY2hhcmFjdGVyKGZpZ3NoYXJlX2Fubm90YXRpb24kY2VsbCksICdmaWdzaGFyZV9hbm5vdGF0aW9uJ10gPC0gYXMuY2hhcmFjdGVyKGZpZ3NoYXJlX2Fubm90YXRpb24kY2VsbF9vbnRvbG9neV9jbGFzcykKVFNORVBsb3Qob2JqZWN0ID0gdGlzcywgZG8ucmV0dXJuID0gVFJVRSwgZ3JvdXAuYnkgPSAiZmlnc2hhcmVfYW5ub3RhdGlvbiIpCmBgYAoKYGBge3J9CnRhYmxlKHRpc3NAbWV0YS5kYXRhJGZpZ3NoYXJlX2Fubm90YXRpb24sIHRpc3NAaWRlbnQpCmBgYAoKCiMjIEFzc2lnbmluZyBjZWxsIHR5cGUgaWRlbnRpdHkgdG8gY2x1c3RlcnMKCkF0IGEgY29hcnNlIGxldmVsLCB3ZSBjYW4gdXNlIGNhbm9uaWNhbCBtYXJrZXJzIHRvIG1hdGNoIHRoZSB1bmJpYXNlZCBjbHVzdGVyaW5nIHRvIGtub3duIGNlbGwgdHlwZXM6CgowOiBhbHBoYQoxOiBiZXRhCjI6IGJldGEKMzogZXhvY3JpbmUKNDogZHVjdAo1OiBkZWx0YQo2OiBnYW1tYQo3OiBlbmRvdGhlbGlhbAo4OiBpbW11bmUKOTogc3RlbGxhdGUKCmBgYHtyfQojIHN0YXNoIGN1cnJlbnQgY2x1c3RlciBJRHMKdGlzcyA8LSBTdGFzaElkZW50KG9iamVjdCA9IHRpc3MsIHNhdmUubmFtZSA9ICJjbHVzdGVyLmlkcyIpCgojIGVudW1lcmF0ZSBjdXJyZW50IGNsdXN0ZXIgSURzIGFuZCB0aGUgbGFiZWxzIGZvciB0aGVtCmNsdXN0ZXIuaWRzIDwtIGMoMCwgMSwgMiwgMywgNCwgNSwgNiwgNywgOCwgOSwgMTApCmNlbGxfb250b2xvZ3lfY2xhc3MgPC0gYygwLCAxLCAyLCAzLCA0LCA1LCA2LCA3LCA4LCA5LCAxMCkKZnJlZV9hbm5vdGF0aW9uIDwtYygiaGVtYXRvcG9pZXRpYyBzdGVtIGNlbGwiLCAiQiBjZWxsIiwgIkIgY2VsbCIsICJuZXV0cm9waGlsIiwgImdyYW51bG9jeXRlIiwgIm1vbm9jeXRlIiwgIkIgY2VsbCIsICJUX05LIiwgIm5ldXRyb3BoaWwiLCAiRnJhY3Rpb24gQSBwcmUtcHJvIEIgY2VsbCIsICJoZW1hdG9wb2lldGljIHN0ZW0gY2VsbCIpCgp2YWxpZGF0ZV9jZWxsX29udG9sb2d5KGNlbGxfb250b2xvZ3lfY2xhc3MpCmNlbGxfb250b2xvZ3lfaWQgPSBjb252ZXJ0X3RvX2NlbGxfb250b2xvZ3lfaWQoY2VsbF9vbnRvbG9neV9jbGFzcykKCnRpc3NAbWV0YS5kYXRhWydmcmVlX2Fubm90YXRpb24nXSA8LSBhcy5jaGFyYWN0ZXIocGx5cjo6bWFwdmFsdWVzKHggPSB0aXNzQGlkZW50LCBmcm9tID0gY2x1c3Rlci5pZHMsIHRvID0gZnJlZV9hbm5vdGF0aW9uKSkKdmFsaWRhdGVfY2VsbF9vbnRvbG9neShjZWxsX29udG9sb2d5X2NsYXNzKQpjZWxsX29udG9sb2d5X2lkID0gY29udmVydF90b19jZWxsX29udG9sb2d5X2lkKGNlbGxfb250b2xvZ3lfY2xhc3MpCgp0aXNzQG1ldGEuZGF0YVsnY2VsbF9vbnRvbG9neV9jbGFzcyddIDwtIGFzLmNoYXJhY3RlcihwbHlyOjptYXB2YWx1ZXMoeCA9IHRpc3NAaWRlbnQsIGZyb20gPSBjbHVzdGVyLmlkcywgdG8gPSBjZWxsX29udG9sb2d5X2NsYXNzKSkKdGlzc0BtZXRhLmRhdGFbJ2NlbGxfb250b2xvZ3lfaWQnXSA8LSBhcy5jaGFyYWN0ZXIocGx5cjo6bWFwdmFsdWVzKHggPSB0aXNzQGlkZW50LCBmcm9tID0gY2x1c3Rlci5pZHMsIHRvID0gY2VsbF9vbnRvbG9neV9pZCkpCgoKClRTTkVQbG90KG9iamVjdCA9IHRpc3MsIGRvLmxhYmVsID0gVFJVRSwgcHQuc2l6ZSA9IDAuNSwgZ3JvdXAuYnk9J2NlbGxfb250b2xvZ3lfY2xhc3MnKQpgYGAKCgojIyBDaGVja2luZyBmb3IgYmF0Y2ggZWZmZWN0cwoKCkNvbG9yIGJ5IG1ldGFkYXRhLCBsaWtlIHBsYXRlIGJhcmNvZGUsIHRvIGNoZWNrIGZvciBiYXRjaCBlZmZlY3RzLgpgYGB7cn0KVFNORVBsb3Qob2JqZWN0ID0gdGlzcywgZG8ucmV0dXJuID0gVFJVRSwgZ3JvdXAuYnkgPSAicGxhdGUuYmFyY29kZSIpCmBgYAoKUHJpbnQgYSB0YWJsZSBzaG93aW5nIHRoZSBjb3VudCBvZiBjZWxscyBpbiBlYWNoIGlkZW50aXR5IGNhdGVnb3J5IGZyb20gZWFjaCBwbGF0ZS4KCmBgYHtyfQp0YWJsZShhcy5jaGFyYWN0ZXIodGlzc0BpZGVudCksIGFzLmNoYXJhY3Rlcih0aXNzQG1ldGEuZGF0YSRwbGF0ZS5iYXJjb2RlKSkKYGBgCgoKIyBTdWJzZXQgYW5kIGl0ZXJhdGUKCldlIGNhbiByZXBlYXQgdGhlIGFib3ZlIGFuYWx5c2lzIG9uIGEgc3Vic2V0IG9mIGNlbGxzLCBkZWZpbmVkIHVzaW5nIGNsdXN0ZXIgSURzIG9yIHNvbWUgb3RoZXIgbWV0YWRhdGEuIFRoaXMgaXMgYSBnb29kIHdheSB0byBkcmlsbCBkb3duIGFuZCBmaW5kIHN1YnN0cnVjdHVyZS4KCgojIyBTdWJzZXQgPT0gVCBhbmQgTksgY2VsbHMgKENsdXN0ZXIgNykKCmBgYHtyfQojIFN1YnNldCBkYXRhIGJhc2VkIG9uIGNsdXN0ZXIgaWQKc3VidGlzczcgPC0gU3Vic2V0RGF0YShvYmplY3QgPSB0aXNzLCBpZGVudC51c2UgPSBjKDcpLCBkby5jZW50ZXIgPSBGLCBkby5zY2FsZSA9IEYsIGNlbGxzLnVzZSA9ICkKCiMgVG8gc3Vic2V0IGRhdGEgYmFzZWQgb24gY2VsbF9vbnRvbG9neV9jbGFzcyBvciBvdGhlciBtZXRhZGF0YSwgeW91IGNhbiBleHBsaWNpdGx5IHBhc3MgY2VsbCBuYW1lcwoKIyBhbm5vID0gJ2V4b2NyaW5lIGNlbGxzJwojIGNlbGxzLnRvLnVzZSA9IHRpc3NAY2VsbC5uYW1lc1t3aGljaCh0aXNzQG1ldGEuZGF0YSRjZWxsX29udG9sb2d5X2NsYXNzID09IGFubm8pXQojIHN1YnRpc3M3IDwtIFN1YnNldERhdGEob2JqZWN0ID0gdGlzcywgY2VsbHMudXNlID0gY2VsbHMudG8udXNlLCBkby5jZW50ZXIgPSBGLCBkby5zY2FsZSA9IEYpCgpgYGAKCmBgYHtyfQpzdWJ0aXNzNyA8LSBOb3JtYWxpemVEYXRhKG9iamVjdCA9IHN1YnRpc3M3KQpzdWJ0aXNzNyA8LSBTY2FsZURhdGEob2JqZWN0ID0gc3VidGlzczcsIHZhcnMudG8ucmVncmVzcyA9IGMoIm5SZWFkcyIsICJwZXJjZW50LnJpYm8iLCJSbjQ1cyIpKQpgYGAKCmBgYHtyfQpzdWJ0aXNzNyA8LSBGaW5kVmFyaWFibGVHZW5lcyhvYmplY3QgPSBzdWJ0aXNzNywgZG8ucGxvdCA9IFRSVUUsIHguaGlnaC5jdXRvZmYgPSBJbmYsIHkuY3V0b2ZmID0gMC44KQpzdWJ0aXNzNyA8LSBSdW5QQ0Eob2JqZWN0ID0gc3VidGlzczcsIHBjcy5jb21wdXRlID0gMjApCnN1YnRpc3M3IDwtIFByb2plY3RQQ0Eob2JqZWN0ID0gc3VidGlzczcsIGRvLnByaW50ID0gRkFMU0UpCmBgYAoKClJ1biBQcmluY2lwYWwgQ29tcG9uZW50IEFuYWx5c2lzLgpgYGB7cn0Kc3VidGlzczcgPC0gUnVuUENBKG9iamVjdCA9IHN1YnRpc3M3LCBkby5wcmludCA9IEZBTFNFKQpzdWJ0aXNzNyA8LSBQcm9qZWN0UENBKG9iamVjdCA9IHN1YnRpc3M3LCBkby5wcmludCA9IEZBTFNFKQpgYGAKCmBgYHtyfQojIElmIHRoaXMgZmFpbHMgZm9yIHlvdXIgc3Vic2V0LCBpdCBtYXkgYmUgdGhhdCBjZWxscy51c2UgaXMgbW9yZSBjZWxscyB0aGFuIHlvdSBoYXZlIGxlZnQhIFRyeSByZWR1Y2luZyBpdC4KUENIZWF0bWFwKG9iamVjdCA9IHN1YnRpc3M3LCBwYy51c2UgPSAxOjMsIGNlbGxzLnVzZSA9IDI1MCwgZG8uYmFsYW5jZWQgPSBUUlVFLCBsYWJlbC5jb2x1bW5zID0gRkFMU0UsIG51bS5nZW5lcyA9IDEyKQpgYGAKCkxhdGVyIG9uIChpbiBGaW5kQ2x1c3RlcnMgYW5kIFRTTkUpIHlvdSB3aWxsIHBpY2sgYSBudW1iZXIgb2YgcHJpbmNpcGFsIGNvbXBvbmVudHMgdG8gdXNlLiBUaGlzIGhhcyB0aGUgZWZmZWN0IG9mIGtlZXBpbmcgdGhlIG1ham9yIGRpcmVjdGlvbnMgb2YgdmFyaWF0aW9uIGluIHRoZSBkYXRhIGFuZCwgaWRlYWxseSwgc3VwcmVzc2luZyBub2lzZS4gVGhlcmUgaXMgbm8gY29ycmVjdCBhbnN3ZXIgdG8gdGhlIG51bWJlciB0byB1c2UsIGJ1dCBhIGRlY2VudCBydWxlIG9mIHRodW1iIGlzIHRvIGdvIHVudGlsIHRoZSBwbG90IHBsYXRlYXVzLgoKYGBge3J9ClBDRWxib3dQbG90KG9iamVjdCA9IHN1YnRpc3M3KQpgYGAKCkNob29zZSB0aGUgbnVtYmVyIG9mIHByaW5jaXBhbCBjb21wb25lbnRzIHRvIHVzZS4KYGBge3J9CiMgU2V0IG51bWJlciBvZiBwcmluY2lwYWwgY29tcG9uZW50cy4gCnN1Yjcubi5wY3MgPSA1CmBgYAoKClRoZSBjbHVzdGVyaW5nIGlzIHBlcmZvcm1lZCBiYXNlZCBvbiBhIG5lYXJlc3QgbmVpZ2hib3JzIGdyYXBoLiBDZWxscyB0aGF0IGhhdmUgc2ltaWxhciBleHByZXNzaW9uIHdpbGwgYmUgam9pbmVkIHRvZ2V0aGVyLiBUaGUgTG91dmFpbiBhbGdvcml0aG0gbG9va3MgZm9yIGdyb3VwcyBvZiBjZWxscyB3aXRoIGhpZ2ggbW9kdWxhcml0eS0tbW9yZSBjb25uZWN0aW9ucyB3aXRoaW4gdGhlIGdyb3VwIHRoYW4gYmV0d2VlbiBncm91cHMuIFRoZSByZXNvbHV0aW9uIHBhcmFtZXRlciBkZXRlcm1pbmVzIHRoZSBzY2FsZS4uLmhpZ2hlciByZXNvbHV0aW9uIHdpbGwgZ2l2ZSBtb3JlIGNsdXN0ZXJzLCBsb3dlciByZXNvbHV0aW9uIHdpbGwgZ2l2ZSBmZXdlci4KCmBgYHtyfQojIFNldCByZXNvbHV0aW9uIApzdWIucmVzLnVzZWQgPC0gMQoKc3VidGlzczcgPC0gRmluZENsdXN0ZXJzKG9iamVjdCA9IHN1YnRpc3M3LCByZWR1Y3Rpb24udHlwZSA9ICJwY2EiLCBkaW1zLnVzZSA9IDE6c3ViNy5uLnBjcywgCiAgICByZXNvbHV0aW9uID0gc3ViLnJlcy51c2VkLCBwcmludC5vdXRwdXQgPSAwLCBzYXZlLlNOTiA9IFRSVUUpCmBgYAoKVG8gdmlzdWFsaXplIApgYGB7cn0KIyBJZiBjZWxscyBhcmUgdG9vIHNwcmVhZCBvdXQsIHlvdSBjYW4gcmFpc2UgdGhlIHBlcnBsZXhpdHkuIElmIHlvdSBoYXZlIGZldyBjZWxscywgdHJ5IGEgbG93ZXIgcGVycGxleGl0eSAoYnV0IG5ldmVyIGxlc3MgdGhhbiAxMCkuCnN1YnRpc3M3IDwtIFJ1blRTTkUob2JqZWN0ID0gc3VidGlzczcsIGRpbXMudXNlID0gMTpzdWI3Lm4ucGNzLCBzZWVkLnVzZSA9IDEwLCBwZXJwbGV4aXR5PTMwKQpgYGAKCmBgYHtyfQojIG5vdGUgdGhhdCB5b3UgY2FuIHNldCBkby5sYWJlbD1UIHRvIGhlbHAgbGFiZWwgaW5kaXZpZHVhbCBjbHVzdGVycwpUU05FUGxvdChvYmplY3QgPSBzdWJ0aXNzNywgZG8ubGFiZWwgPSBUKQpgYGAKCmBgYHtyfQpzdWJ0aXNzNy5tYXJrZXJzIDwtIEZpbmRBbGxNYXJrZXJzKG9iamVjdCA9IHN1YnRpc3M3LCBvbmx5LnBvcyA9IFRSVUUsIG1pbi5wY3QgPSAwLjI1LCB0aHJlc2gudXNlID0gMC4yNSkKYGBgCgpgYGB7cn0Kc3VidGlzczcubWFya2VycyAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIHRvcF9uKDYsIGF2Z19kaWZmKQpgYGAKCkNoZWNrIGV4cHJlc3Npb24gb2YgZ2VuZXMgb2YgaW50ZXJzZXQuCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTQ4LCBmaWcud2lkdGg9MTV9CmdlbmVzX3RvX2NoZWNrID0gYygnQ2Q2JywnSWw3cicsJ0N0bGE0JywnQ2Q4YjEnLCAnQ3hjcjYnLCAnQ2Q4YScsICdUeXJvYnAnLCAnTmNyMScsICdDZDNlJywgJ0tscmIxYScsICdLbHJiMWMnLCAnR3ptYScsICdQcmYxJywgJ1NlcnBpbmI5JywgJ0x5ejInLCAnTmdwJywgJ0hwJywgJ0x5NmMyJywgJ0NkNzlhJywgJ0NkNzQnLCAnSDItQWEnLCAnSDItQWIxJywgJ0NkNzliJywgJ0gyLUViMScsICdDY25hMicsICdTdG1uMScsICdUb3AyYScsICdNa2k2NycsICdScm0yJywgJ05rZzcnKQoKRmVhdHVyZVBsb3Qoc3VidGlzczcsIGdlbmVzX3RvX2NoZWNrLCBwdC5zaXplID0gMSwgbkNvbCA9IDMpCmBgYAoKRG90cGxvdHMgbGV0IHlvdSBzZWUgdGhlIGludGVuc2l0eSBvZiBleHBwcmVzc2lvbiBhbmQgdGhlIGZyYWN0aW9uIG9mIGNlbGxzIGV4cHJlc3NpbmcgZm9yIGVhY2ggb2YgeW91ciBnZW5lcyBvZiBpbnRlcmVzdC4KCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD0zMH0KIyBUbyBjaGFuZ2UgdGhlIHktYXhpcyB0byBzaG93IHJhdyBjb3VudHMsIGFkZCB1c2UucmF3ID0gVC4KRG90UGxvdChzdWJ0aXNzNywgZ2VuZXNfdG9fY2hlY2ssIHBsb3QubGVnZW5kID0gVCkKYGBgCgpIb3cgYmlnIGFyZSB0aGUgY2x1c3RlcnM/CmBgYHtyfQp0YWJsZShzdWJ0aXNzN0BpZGVudCkKYGBgCgojIyBDaGVja2luZyBmb3IgYmF0Y2ggZWZmZWN0cwoKQ29sb3IgYnkgbWV0YWRhdGEsIGxpa2UgcGxhdGUgYmFyY29kZSwgdG8gY2hlY2sgZm9yIGJhdGNoIGVmZmVjdHMuCmBgYHtyfQpUU05FUGxvdChvYmplY3QgPSBzdWJ0aXNzNywgZG8ucmV0dXJuID0gVFJVRSwgZ3JvdXAuYnkgPSAicGxhdGUuYmFyY29kZSIpCmBgYAoKUHJpbnQgYSB0YWJsZSBzaG93aW5nIHRoZSBjb3VudCBvZiBjZWxscyBpbiBlYWNoIGlkZW50aXR5IGNhdGVnb3J5IGZyb20gZWFjaCBwbGF0ZS4KCmBgYHtyfQp0YWJsZShhcy5jaGFyYWN0ZXIoc3VidGlzczdAaWRlbnQpLCBhcy5jaGFyYWN0ZXIoc3VidGlzczdAbWV0YS5kYXRhJHBsYXRlLmJhcmNvZGUpKQpgYGAKCgoKIyMjIEFzc2lnbmluZyBzdWJjZWxsX29udG9sb2d5X2NsYXNzcwoKRm9yIHRoZSBzdWJzZXRzLCB3ZSBwcm9kdWNlIHN1YmNlbGxfb250b2xvZ3lfY2xhc3NzLiBUaGVzZSB3aWxsIGJlIHdyaXR0ZW4gYmFjayBhcyBtZXRhZGF0YSBpbiB0aGUgb3JpZ2luYWwgb2JqZWN0LCBzbyB3ZSBjYW4gc2VlIGFsbCBzdWJjZWxsX29udG9sb2d5X2NsYXNzcyB0b2dldGhlci4KCklmIHNvbWUgb2YgdGhlIGNsdXN0ZXJzIHlvdSBmaW5kIGluIHRoZSBzdWJzZXQgZGVzZXJ2ZSBhZGRpdGlvbmFsIGNlbGxfb250b2xvZ3lfY2xhc3MsIHlvdSBjYW4gYWRkIHRoYXQgcmlnaHQgaGVyZS4gVXNlIE5BIGZvciBjbHVzdGVycyBmb3Igd2hpY2ggbm8gc3ViY2VsbF9vbnRvbG9neV9jbGFzcyBpcyBuZWVkZWQuCgpgYGB7cn0Kc3ViY2x1c3Rlci5pZHMgPC0gYygwLCAxLCAyLCAzLCA0LCA1KQpzdWJjZWxsX29udG9sb2d5X2NsYXNzIDwtCiAgYygiVCBjZWxsIiwKICAibmF0dXJhbCBraWxsZXIgY2VsbCIsCiAgIm5hdHVyYWwga2lsbGVyIGNlbGwiLAogICJUIGNlbGwiLAogICJUIGNlbGwiLAogICJUIGNlbGwiKQogIGNlbGxfb250b2xvZ3lfaWQgPSBjKCJDTDowMDAwMDg0IiwKICAiQ0w6MDAwMDYyMyIsCiAgIkNMOjAwMDA2MjMiLAogICJDTDowMDAwMDg0IiwKICAiQ0w6MDAwMDA4NCIsCiAgIkNMOjAwMDAwODQiKQoKc3VidGlzczdAbWV0YS5kYXRhWywnY2VsbF9vbnRvbG9neV9jbGFzcyddIDwtIHBseXI6Om1hcHZhbHVlcyh4ID0gc3VidGlzczdAaWRlbnQsIGZyb20gPSBzdWJjbHVzdGVyLmlkcywgdG8gPSBzdWJjZWxsX29udG9sb2d5X2NsYXNzKQpzdWJ0aXNzN0BtZXRhLmRhdGFbLCdjZWxsX29udG9sb2d5X2lkJ10gPC0gcGx5cjo6bWFwdmFsdWVzKHggPSBzdWJ0aXNzN0BpZGVudCwgZnJvbSA9IHN1YmNsdXN0ZXIuaWRzLCB0byA9IGNlbGxfb250b2xvZ3lfaWQpCgp0aXNzQG1ldGEuZGF0YVtzdWJ0aXNzN0BjZWxsLm5hbWVzLCdjZWxsX29udG9sb2d5X2NsYXNzJ10gPC0gYXMuY2hhcmFjdGVyKHN1YnRpc3M3QG1ldGEuZGF0YSRjZWxsX29udG9sb2d5X2NsYXNzKQp0aXNzQG1ldGEuZGF0YVtzdWJ0aXNzN0BjZWxsLm5hbWVzLCdjZWxsX29udG9sb2d5X2lkJ10gPC0gYXMuY2hhcmFjdGVyKHN1YnRpc3M3QG1ldGEuZGF0YSRjZWxsX29udG9sb2d5X2lkKQoKVFNORVBsb3Qob2JqZWN0ID0gc3VidGlzczcsIGRvLmxhYmVsID0gVFJVRSwgcHQuc2l6ZSA9IDAuNSwgZ3JvdXAuYnk9J2NlbGxfb250b2xvZ3lfY2xhc3MnKQpgYGAKCldoZW4geW91IHNhdmUgdGhlIHN1YnRpc3N1ZSwgcGxlYXNlIGdpdmUgaXQgYSBuYW1lLgoKYGBge3J9CnN1YnRpc3M3Lm5hbWUgPSAnTmtfVF9jZWxscycKc2F2ZShzdWJ0aXNzNywgZmlsZT1wYXN0ZTAoc2F2ZV9kaXIsIi8iLHN1YnRpc3M3Lm5hbWUsICJfc2V1cmF0X3N1YnRpc3M3LlJvYmoiKSkKYGBgCgoKIyBFeHBvcnQgdGhlIGZpbmFsIG1ldGFkYXRhCgpTbyB0aGF0IEJpb2h1YiBjYW4gZWFzaWx5IGNvbWJpbmUgYWxsIHlvdXIgY2VsbF9vbnRvbG9neV9jbGFzc3MsIHBsZWFzZSBleHBvcnQgdGhlbSBhcyBhIHNpbXBsZSBjc3YuCgpgYGB7cn0Kd3JpdGUuY3N2KHRpc3NAbWV0YS5kYXRhWyxjKCdwbGF0ZS5iYXJjb2RlJywnY2VsbF9vbnRvbG9neV9jbGFzcycsJ3N1YmNlbGxfb250b2xvZ3lfY2xhc3MnKV0sZmlsZSA9cGFzdGUwKHNhdmVfZGlyLCIvIiwgdGlzc3VlX29mX2ludGVyZXN0LCJfY2VsbF9vbnRvbG9neV9jbGFzcy5jc3YiKSkKYGBgCgoKCgpXcml0ZSB0aGUgY2VsbCBvbnRvbG9neSBhbmQgZnJlZSBhbm5vdGF0aW9ucyB0byBDU1YuCgpgYGB7cn0KZmlsZW5hbWUgPSBoZXJlKCcwMF9kYXRhX2luZ2VzdCcsICcwM190aXNzdWVfYW5ub3RhdGlvbl9jc3YnLCAKICAgICAgICAgICAgICAgICAgICBwYXN0ZTAodGlzc3VlX29mX2ludGVyZXN0LCAiX2ZhY3NfYW5ub3RhdGlvbi5jc3YiKSkKd3JpdGUuY3N2KHRpc3NAbWV0YS5kYXRhWyxjKCdwbGF0ZS5iYXJjb2RlLCdjZWxsX29udG9sb2d5X2NsYXNzJywnY2VsbF9vbnRvbG9neV9pZCcsICdmcmVlLmFubm90YXRpb24nKV0sIGZpbGU9ZmlsZW5hbWUpCmBgYAo=